package com.ming.common.liteflow.core.flow.logicflow;

import com.ming.common.liteflow.context.IvyLoadCmp;
import com.ming.common.liteflow.core.dynamic.IvyDynamicClass;
import com.ming.common.liteflow.core.el.Flow;
import com.ming.common.liteflow.core.exec.ELExecUtil;
import com.ming.common.liteflow.core.execption.LiteFlowELException;
import com.ming.common.liteflow.core.graph.GraphEL;
import com.ming.common.liteflow.core.graph.Node;
import com.ming.common.liteflow.core.node.IvyCmp;
import com.ming.common.util.CommonUtil;
import com.yomahub.liteflow.builder.el.ELWrapper;
import com.yomahub.liteflow.core.FlowExecutor;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class LogicFlow {

    public String json;
    public List<LogicFlowGraphEL> graphELList;
    private List<IvyDynamicClass> dynamicClassList;
    public boolean formatEL = false;
    public ELWrapper wrapper;
    public List<IvyCmp> nodeInfoList = new ArrayList<>();
    private FlowExecutor flowExecutor;

    private LogicFlow(){
        this.graphELList = new ArrayList<>();
    }

    public static LogicFlow NEW(){
        return new LogicFlow();
    }

    public LogicFlow json(String json){
        this.json = json;
        return this;
    }

    public LogicFlow transform() throws LiteFlowELException {
        this.wrapper = LogicflowElUtil.transform(this);
        return this;
    }

    public LogicFlow dynamicClassList(List<IvyDynamicClass> list) {
        this.dynamicClassList = list;
        return this;
    }

    public LogicFlow flowExecutor(FlowExecutor flowExecutor){
        this.flowExecutor = flowExecutor;
        return this;
    }

    public LogicFlow formatEL(){
        this.formatEL = true;
        return this;
    }

    public String buildEL(){
        return wrapper.toEL(formatEL);
    }

    public String buildEL(boolean formatEL){
        if(wrapper != null){
            return wrapper.toEL(formatEL);
        }
        return null;
    }

    public List<Node> flowNodeList(){
        List<Node> flowNodeList = new ArrayList<>();
        for (LogicFlowGraphEL graphEL : graphELList){
            List<Node> list = graphEL.getList().keySet().stream().collect(Collectors.toList());
            flowNodeList.addAll(list);
        }
        return flowNodeList;
    }

    public List<Node> fallbackList(){
        List<Node> fallbackList = new ArrayList<>();
        for (LogicFlowGraphEL graphEL : graphELList){
            if(CommonUtil.collUtil.isNotEmpty(graphEL.getFallbackList())){
                fallbackList.addAll(graphEL.getFallbackList());
            }
        }
        return fallbackList;
    }

    public String exec(){
        IvyLoadCmp.loadCmp(json);

        if(graphELList.size() == 1){
            LogicFlowGraphEL graphEL = graphELList.get(0);
            List<Node> flowNodeList = graphEL.getList().keySet().stream().collect(Collectors.toList());
            return ELExecUtil.exec(flowExecutor, nodeInfoList,dynamicClassList, flowNodeList, graphEL.getFallbackList(), wrapper.toEL());
        }
        List<Node> flowNodeList = new ArrayList<>();
        List<Node> fallbackList = new ArrayList<>();
        for (LogicFlowGraphEL graphEL : graphELList){
            List<Node> list = graphEL.getList().keySet().stream().collect(Collectors.toList());
            flowNodeList.addAll(list);
            if(CommonUtil.collUtil.isNotEmpty(graphEL.getFallbackList())){
                fallbackList.addAll(graphEL.getFallbackList());
            }
        }
        return ELExecUtil.exec(flowExecutor, nodeInfoList,dynamicClassList, flowNodeList, fallbackList, wrapper.toEL());
    }
}
